package Hard;
// 44.通配符匹配  dp专项训练 4.21每日一题
/*
 * 给定一个字符串 (s) 和一个字符模式 (p) ，实现一个支持 '?' 和 '*' 的通配符匹配。
 * '?' 可以匹配任何单个字符。'*' 可以匹配任意字符串（包括空字符串）。
 * 两个字符串完全匹配才算匹配成功。
 * s 可能为空，且只包含从 a-z 的小写字母。
 * p 可能为空，且只包含从 a-z 的小写字母，以及字符 ? 和 *。
 * */

/*
 * -------------------------------------------------------------
 * 思路：
 * dp[i][j]表示 截止到字符串s的第i个位置和字符串p的第j个位置，能否成功匹配
 * dp[0][0]初始化为true，因为空字符串一定和空字符串匹配
 * i和j代表的是真实下标，而不是数组下标。所以写程序的时候注意要-1的地方
 * -------------------------------------------------------------
 * 当p[j]=='?'时，dp[i][j] = dp[i-1][j-1]
 * 当p[j]=='*'时，dp[i][j] = true(if 存在dp[i-X][j-1]==true ,X可以取0，1，2...s.length)
 *         else: dp[i][j] = false
 * OtherWise:
 * if(s[i]==p[j])  dp[i][j] = dp[i-1][j-1]
 * else: dp[i][j] = false
 * -------------------------------------------------------------
 * 返回：  dp[s.length][p.length]
 * */
public class Solution44 {
    public boolean isMatch(String s, String p) {
        // 首先考虑特殊情况，s为空
        if (s.length() == 0) {
            //只要p里存在不为*的字符，就返回false，否则返回true
            for (int i = 0; i < p.length(); i++) {
                if (p.charAt(i) != '*')
                    return false;
            }
            return true;
        }
        // 特殊情况：p为空，只要s不为空，则返回false
        if (s.length() != 0 && p.length() == 0)
            return false;
        int i = 0, j = 0;
        boolean[][] dp = new boolean[s.length() + 1][p.length() + 1];
        dp[0][0] = true;
        dp[1][0] = false;
        if (p.charAt(0) == '*') {
            dp[0][1] = true;
            // 特殊情况： p: [***h0]
            // 要首先查看p开头有几个*
            for (int i1 = 1; i1 < p.length(); i1++) {
                if (p.charAt(i1) == '*') {
                    dp[0][i1 + 1] = true;
                } else {
                    dp[0][i1 + 1] = false;
                    break;
                }
            }
        } else
            dp[0][1] = false;
        // 初始化完毕，开始dp
        for (i = 1; i < dp.length; i++) {
            for (j = 1; j < dp[0].length; j++) {
                if (p.charAt(j - 1) == '*') {
                    // 寻找是否存在dp[i-X][j-1]==true，如果存在，则dp[i][j] = true
                    int X;
                    for (X = 0; X <= i; X++) {
                        if (dp[i - X][j - 1] == true) {
                            dp[i][j] = true;
                            break;
                        }
                    }
                    if (X > i) {
                        dp[i][j] = false;
                    }
                } else if (p.charAt(j - 1) == '?') {
                    dp[i][j] = dp[i - 1][j - 1];
                } else {
                    // p[j]为其他字符的情况
                    if (s.charAt(i - 1) == p.charAt(j - 1)) {
                        dp[i][j] = dp[i - 1][j - 1];
                    } else {
                        dp[i][j] = false;
                    }
                }
            }
        }
        return dp[s.length()][p.length()];
    }
}
